package cn.ingrun.utils.redisUtil;

import cn.ingrun.utils.stringUtil.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {

    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 26
     * 指定缓存失效时间
     * 27
     *
     * @param key  键
     *             28
     * @param time 时间(秒)
     *             29
     * @return 30
     */

    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 44
     * 根据key 获取过期时间
     * 45
     *
     * @param key 键 不能为null
     *            46
     * @return 时间(秒) 返回0代表为永久有效
     * 47
     */

    @SuppressWarnings("all")
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    public void set(String key, String value){
        redisTemplate.opsForValue().set(key, value);
    }

    public void set(String key, String value, long time){
        // 直接设置过期时间会导致value值异常
        redisTemplate.opsForValue().set(key, value);
        this.expire(key, time);
    }

    public String get(String key){
        if ( ! hasKey(key) ){
            return "";
        }
        return (String) redisTemplate.opsForValue().get(key);
    }

    public void hashSet(String key, String hashKey,  Object o){
        redisTemplate.opsForHash().put(key, hashKey, o);
    }

    public void hashSet(String key, String hashKey, Object o, long time){
        hashSet(key, hashKey, o);
        if (time > 0){
            expire(key, time);
        }
    }

    public Object hashGet(String key, String hashKey){
        return redisTemplate.opsForHash().get(key,hashKey);
    }

    // 删除单个hash 的 hashKey
    public void hashDel(String key, String hashKey){
        redisTemplate.opsForHash().delete(key, hashKey);
    }

    // 以 hash 保存 object
    public void setObject(String key, Object obj){
        String classname =  obj.getClass().getName();

        try {
            Class<?> cla = Class.forName(classname);
            Field[] field = cla.getDeclaredFields();  // 字段

            for (Field i: field) {
                i.setAccessible(true);   // 获得私有变量
                this.hashSet(key, i.getName(), i.get(obj));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    // 以 hash 保存 object
    public void setObject(String key, Object obj, long time){
        String classname =  obj.getClass().getName();

        try {
            Class<?> cla = Class.forName(classname);
            List<Field[]> field = new ArrayList<Field[]>();
            for(; cla!=Object.class ;cla = cla.getSuperclass() ){
                Field[] f = cla.getDeclaredFields();  // 字段
                field.add(f);
            }
//            Field[] field = cla.getDeclaredFields();  // 字段

            for (Field[] aField : field) {
                for (Field k : aField) {
                    k.setAccessible(true);   // 获得私有变量
                    this.hashSet(key, k.getName(), k.get(obj), time);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 从 hash 中获取 object
    public <T> T getObject(String key, Class<T> cla){
        if (!this.hasKey(key)){
            return null;
        }
        try {
            T o = cla.getDeclaredConstructor().newInstance();

            List<Field[]> field2 = new ArrayList<Field[]>();
            Class<?> obj = cla;

            for(; obj!=Object.class ;obj = cla.getSuperclass()){
                Field[] f = cla.getDeclaredFields();  // 字段
                field2.add(f);
            }

            for (Field[] af:field2) {
                for (Field f:af) {
                    f.setAccessible(true);   // 获得私有变量
                    if (Modifier.isFinal(f.getModifiers())){
                        System.out.println( f );
                        continue;
                    }
                    Object id = this.hashGet(key, f.getName());
                    f.set(o, id);
                }
            }

            return o;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // key  是否存在
    public Boolean hasKey(String key){
        return redisTemplate.hasKey(key);
    }

    // 删除
    public Boolean del(String key){
        if (StringUtils.isNullOrEmpty(key)){
            return false;
        }
        return redisTemplate.delete(key);
    }

    @SuppressWarnings("all")
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    @SuppressWarnings("all")
    public long incr(String key) {
        return redisTemplate.opsForValue().increment(key);
    }


}
